Spring Security Note-16
基于JWT实现SSO单点登录
问题
在实际生活的应用中,我们举个例子而言,对于淘宝和天猫这两个完全不同的域名,是两个完全不同的服务器上;
我们在淘宝进行登录的时候,跳转到了一个域名为
login.taobao.com
意味着,服务器又换了一个,到此已经出现了三个服务器;
登录后,页面又跳转回到了淘宝,此时我们重新刷新天猫,天猫也以直接完成了登录状态;
虽然这两个网站是独立的域名,独立的服务器,但是在其中一个网站登录,在另一个网站上实现了登录;
步骤流程
应用A(淘宝) 应用B(天猫) 和认证服务器(登录服务器);
0.用户访问请求登录应用A;
1.应用A将会向认证服务器发起请求授权的请求;
2.此时在认证服务器中获取认证并授权(登录)之后;
3.认证服务区将会返回一个授权码给应用A;
4.获得授权码后,应用A会再次请求认证服务器请求令牌;
5.认证服务器接受请求,返回JWT配置下的令牌,返回给应用A;
6.应用A获得JWT令牌后,进行解析,并且完成登录;
7.当用户访问另一个系统(应用B);
8.应用B也会去认证服务器请求授权;
9.但是在认证服务器中,已存在授权记录,那么认证服务器是知道用户是谁;
10.完成整个OAuth流程,并且返回应用B一个JWT令牌(不同于应用A);
11.应用B获取到认证服务器返回给应用B的JWT进行解析并登录;
12.真正的业务是部署在一个独立的资源服务器,我们只需要使用JWT访问资源服务器即可;
PS:尽管应用A和应用B的JWT不同,但是解析出来的用户信息是一致的;
实现
我们需要重新新建项目sso-demo,在sso这个项目中,我们需要对认证服务器进行一个重新的构造,这个认证服务器是基于浏览器,session的技术;
创建四个项目;
认证服务器配置SSOAuthorizationServerConfig
1 | /** |
配置文件
1 | server.port=9999 |
应用A
1 |
|
1 | # OAuth认证(与服务器配置要一致) |
应用B
1 | # OAuth认证(与服务器配置要一致) |
测试
1.首先访问127.0.0.1:8080/client1/index.html
2.跳转登录认证(9999)
username:user
password:123123
3.是否授权给APP1访问受保护的资源?
4.得到授权后返回,此时已获得认证服务器的授权
5.访问/user
,获取用户信息
6.访问Client2,这时候,认证服务器已经知道我的用户信息,不需要重新登录,只需要授权即可
7.此时即可完成Client1和Client2页面之间任意的跳转
8.这时候我们会发现Client1和Client2访问/user
所获得的tokenValue
是不同的,但是用户信息是一样的;
改善
登录页面和A跳转B的隐藏授权;
登录
在Server项目中,重新configure为表单登录的方式;
1 |
|
不将用户名和密码写死,通过重新实现UserDetailsService的方式,从数据库中读写用户名和密码;
1 |
|
覆盖
1 |
|
-
授权
找到授权的表单的页面在WhitelabelApprovalEndpoint
类,在进入时直接跳转授权,不需要点击;
重新写一个WhitelabelApprovalEndpoint
,将@FrameworkEndpoint改为@RestController进行处理;
并且复制一份SpelView
为SsoSpelView
;
我们直接将confirmationForm提交,并且隐藏<body></body>
;
1 | <html> |